package com.bright.ghj.overt.service.impl;

import com.bright.ghj.overt.constant.PublicConstant;
import com.bright.ghj.overt.manager.OpenReportRecordManager;
import com.bright.ghj.overt.pojo.command.OpenReportOperateCommand;
import com.bright.ghj.overt.pojo.command.OpenReportOperateIdsCommand;
import com.bright.ghj.overt.pojo.command.YearsMonthsZtIdCommand;
import com.bright.ghj.overt.pojo.dto.OpenReportRecordDTO;
import com.bright.ghj.overt.pojo.po.primary.FlowLog;
import com.bright.ghj.overt.pojo.query.OpenReportRecordQuery;
import com.bright.ghj.overt.pojo.query.TableDataIdQuery;
import com.bright.ghj.overt.pojo.vo.FlowLogVO;
import com.bright.ghj.overt.repository.primary.FlowLogRepository;
import com.bright.ghj.overt.service.OpenReportRecordOperateService;
import com.bright.ghj.overt.service.OperateService;
import com.bright.ghj.common.util.ListUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author hxj
 * @Date 2024/2/29 16:42
 * @Description 审核发布流程（不使用flowable等工作流）
 */
@Slf4j
@Component
@RequiredArgsConstructor
@Qualifier("operateNoFlow")
public class OperateNoFlowServiceImpl implements OperateService {

    private final OpenReportRecordManager openReportRecordManager;
    private final FlowLogRepository flowLogRepository;

    @Override
    public void readyAudit(OpenReportOperateIdsCommand command) {
        List<OpenReportRecordDTO> openList = getOpenListByOperateCommand(command);
        if (openList.size() > 0) {
            operateCommonMethod(command, openList, false, true, false, false,
                    null, openReportRecordManager::setReadyAuditStatus);
        }
    }

    @Override
    public void audit(OpenReportOperateCommand command) {
        List<OpenReportRecordDTO> openList = getOpenListByOperateCommand(command);
        if (openList.size() > 0) {
            operateCommonMethod(command, openList, false, true, false, true,
                    PublicConstant.FLOW_TYPE_AUDIT, openDTO -> {
                        if (command.isFlag()) {
                            openReportRecordManager.setAuditSuccessAndReadyPublishStatus(openDTO, command.getOperator());
                        } else {
                            openReportRecordManager.setAuditFailStatus(openDTO, command.getOperator());
                        }
                    });
        }
    }

    @Override
    public void cancelAudit(OpenReportOperateCommand command) {
        List<OpenReportRecordDTO> openList = getOpenListByOperateCommand(command);
        if (openList.size() > 0) {
            operateCommonMethod(command, openList, true, false, false, true,
                    PublicConstant.FLOW_TYPE_NOT_AUDIT, openDTO -> openReportRecordManager.setReturnToStartStatus(openDTO, command.getOperator()));
        }
    }

    @Override
    public void publish(OpenReportOperateCommand command) {
        List<OpenReportRecordDTO> openList = getOpenListByOperateCommand(command);
        if (openList.size() > 0) {
            operateCommonMethod(command, openList, true, false, false, true,
                    PublicConstant.FLOW_TYPE_PUBLISH, openDTO -> openReportRecordManager.setPublishedStatus(openDTO, command.getOperator()));
        }
    }

    @Override
    public void cancelPublish(OpenReportOperateCommand command) {
        List<OpenReportRecordDTO> openList = getOpenListByOperateCommand(command);
        if (openList.size() > 0) {
            operateCommonMethod(command, openList, false, false, true, false,
                    PublicConstant.FLOW_TYPE_NOT_PUBLISH, openDTO -> openReportRecordManager.setAuditSuccessAndReadyPublishStatus(openDTO, command.getOperator()));
        }
    }

    @Override
    public List<FlowLogVO> listLogs(TableDataIdQuery tableDataIdQuery) {
        List<FlowLog> flowLogs = flowLogRepository.findByOpenIdOrderById(tableDataIdQuery.getId());
        List<FlowLogVO> flowLogVOS = new ArrayList<>();
        for (FlowLog flowLog : flowLogs) {
            FlowLogVO flowLogVO = new FlowLogVO();
            flowLogVO.setOperator(flowLog.getWriter());
            flowLogVO.setDate(flowLog.getWriteDate());
            flowLogVO.setType(flowLog.getOperateType());
            flowLogVO.setOpinion(flowLog.getOpinion());
            flowLogVO.setFlag(flowLog.getFlag() == null ? "" : (flowLog.getFlag() ? "通过" : "不通过"));
            flowLogVOS.add(flowLogVO);
        }
        return flowLogVOS;
    }

    private List<OpenReportRecordDTO> getOpenListByOperateCommand(OpenReportOperateCommand command) {
        if (command instanceof YearsMonthsZtIdCommand) {
            YearsMonthsZtIdCommand ymzCommand = (YearsMonthsZtIdCommand) command;
            OpenReportRecordQuery query = new OpenReportRecordQuery();
            query.setYears(ymzCommand.getYears());
            query.setMonths(ymzCommand.getMonths());
            query.setZtIds(ymzCommand.getZtIds());
            query.setYwType(ymzCommand.getYwType());
            return openReportRecordManager.listByCondition(query, PublicConstant.LIST_TYPE_EDIT);
        } else {
            OpenReportOperateIdsCommand idsCommand = (OpenReportOperateIdsCommand) command;
            List<Integer> ids = ListUtil.toIntegerListByArray(idsCommand.getIds());
            return openReportRecordManager.listById(ids);
        }
    }

//    private void checkAuditPublishStatus(OpenReportRecordDTO openReportRecordDTO, int openCount, boolean isCheckAudit, boolean isCheckNotAudit,
//                                         boolean isCheckPublish, boolean isCheckNotPublish) {
//
//            Integer id = openReportRecordDTO.getId();
//
//            boolean isAudit = openReportRecordManager.isAudit(openReportRecordDTO);
//            if (isCheckNotAudit && isAudit) {
//                String message = "该数据已审核";
//                cancelOperation(openCount, id, message);
//
//            }
//            if (isCheckAudit && !isAudit) {
//                String message = "该数据未审核";
//                cancelOperation(openCount, id, message);
//
//            }
//
//            // 验证是否发布
//            boolean isPublished = openReportRecordManager.isPublished(openReportRecordDTO);
//            if (isCheckNotPublish && isPublished) {
//                String message = "该数据已发布";
//                cancelOperation(openCount, id, message);
//
//            }
//            if (isCheckPublish && !isPublished) {
//                String message = "该数据未发布";
//                cancelOperation(openCount, id, message);
//
//            }
//    }

    // 取消操作 如果是单个id 则返回报错 否则直接略过
    private void cancelOperation(int idCount, int id, String message) {
        if (idCount == 1) {
            throw new RuntimeException(id + message + "，操作取消！");
        } else {
            log.info(id + message + "，跳过");
        }
    }

    private FlowLog getFlowLog(OpenReportRecordDTO dto, String operateType, Boolean flag, String opinion, String writer) {
        FlowLog flowLog = new FlowLog();
        flowLog.setOpenId(dto.getId());
        flowLog.setYears(dto.getYears());
        flowLog.setMonths(dto.getMonths());
        flowLog.setDays(dto.getDays());
        flowLog.setZtId(dto.getZtId());
        flowLog.setTableName(dto.getTableName());
        flowLog.setSno(dto.getSno());
        flowLog.setOperateType(operateType);
        flowLog.setFlag(flag);
        flowLog.setOpinion(opinion);
        flowLog.setWriter(writer);
        flowLog.setWriteDate(new Date());
        return flowLog;
    }

    /**
     * 通用流程操作方法
     * @param command 前端提交的command参数
     * @param openList open数据列表
     * @param isCheckAudit 是否已审核（未审核则报错/跳过）
     * @param isCheckNotAudit 是否未审核
     * @param isCheckPublish 是否已发布
     * @param isCheckNotPublish 是否未发布
     * @param operateType 操作类型
     * @param operateService 用于各种流程操作执行自己业务的接口
     */
    private void operateCommonMethod(OpenReportOperateCommand command, List<OpenReportRecordDTO> openList,
                                     boolean isCheckAudit, boolean isCheckNotAudit,
                                     boolean isCheckPublish, boolean isCheckNotPublish,
                                     String operateType, OpenReportRecordOperateService operateService) {
        log.debug("开始" + operateType);
        List<FlowLog> flowLogs = new ArrayList<>();
        int openCount = openList.size();
        for (OpenReportRecordDTO openReportRecordDTO : openList) {
            // 检查是否符合状态
            Integer id = openReportRecordDTO.getId();

            boolean isAudit = openReportRecordManager.isAuditOK(openReportRecordDTO);
            if (isCheckNotAudit && isAudit) {
                String message = "该数据已审核";
                cancelOperation(openCount, id, message);
                continue;
            }
            if (isCheckAudit && !isAudit) {
                String message = "该数据未审核";
                cancelOperation(openCount, id, message);
                continue;
            }

            // 验证是否发布
            boolean isPublished = openReportRecordManager.isPublished(openReportRecordDTO);
            if (isCheckNotPublish && isPublished) {
                String message = "该数据已发布";
                cancelOperation(openCount, id, message);
                continue;
            }
            if (isCheckPublish && !isPublished) {
                String message = "该数据未发布";
                cancelOperation(openCount, id, message);
                continue;
            }
            // 各流程操作自己的业务
            operateService.process(openReportRecordDTO);

            // 插入流程操作记录 全部遍历完一起提交
            flowLogs.add(getFlowLog(openReportRecordDTO, operateType, command.isFlag(), command.getOpinion(), command.getOperator()));
        }
        openReportRecordManager.saveAll(openList);
        flowLogRepository.saveAll(flowLogs);
        log.debug(operateType + "结束（" + openCount + "条）");
    }

}
